不动jar文件,通过java agent来修改java类
辽宁省赛线下awd,出了那么一道java题:
1 2 3 4 5 6 7 8 9 10 11
| @PostMapping({"/cmd"}) @ResponseBody public String cmd(@RequestParam String command) throws Exception { Base64.getDecoder(); StringBuffer sb = new StringBuffer(""); String[] c = {"/bin/bash", "-c", command}; Process p = Runtime.getRuntime().exec(c); CopyInputStream(p.getInputStream(), sb); CopyInputStream(p.getErrorStream(), sb); return sb.toString(); }
|
遗憾的是:只有3个队伍会修。而我们正因为不会修,屈居第四(还好kali上有个jadx-gui,但是为什么jadx-gui只能看不能改啊!!)。
研究了一下,发现了java agent这个东西,可以弄出类似hook的效果(感觉不如。。xposed),但是感觉有很多坑,环境方面,所以记录一下。
首先最不重要的代码部分是从这里参考的,加了点针对函数重载的精确搜索(关于java agent的介绍也可以看这里):https://www.cnblogs.com/rickiyang/p/11368932.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| package agent2;
import java.io.IOException; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; import java.lang.instrument.Instrumentation; import java.security.ProtectionDomain; import javassist.*;
public class PreMainAgent {
public static void premain(String agentArgs, Instrumentation inst) { System.out.println("agentArgs : " + agentArgs); inst.addTransformer(new DefineTransformer(), true); }
static class DefineTransformer implements ClassFileTransformer {
@Override public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { if (!"com/example/ezjava/controller/EvilController".equals(className)) { return null; } System.out.println("premain load Class:" + className); try { System.out.println("trying!"); final ClassPool classPool = ClassPool.getDefault(); final CtClass clazz = classPool.get("com.example.ezjava.controller.EvilController"); final CtClass str_class = classPool.get("java.lang.String"); System.out.println(str_class); CtMethod cmd = clazz.getDeclaredMethod("cmd", new CtClass[]{str_class}); String methodBody = "{return \"stupid!\";}"; System.out.println("Setting body!"); cmd.setBody(methodBody);
byte[] byteCode = clazz.toBytecode(); clazz.detach(); System.out.println("returning!"); return byteCode; } catch (IOException | CannotCompileException | NotFoundException e) { System.out.println("Error!"); System.out.println(e); return null; } } } }
|
坑部分:
下载javassist.jar
。
然后他用的是maven来改manifest,但是我一直没有找到把依赖打进包里的办法,就改用ant了。
IDE我用的netbeans。可以直接在Libraries上右键添加jar。
修改manifest参考这个链接:https://www.javaxt.com/wiki/Tutorials/Netbeans/How_to_Add_Version_Information_to_a_Jar_File_with_Netbeans
但是,其中的这部分不太对
First, you must update your Netbeans “project.properties” file found in the “nbproject” directory. Add the following line to the file:
manifest.file=manifest.mf
应该是把project.properties
里的manifest.file=manifest.mf
改成manifest.file=MANIFEST.MF
manifest里除了Premain-Class
和Agent-Class
以外还要再加两行(记得把他写的乱七八糟的属性都删掉):
1 2
| <attribute name="Can-Redefine-Classes" value="true"/> <attribute name="Can-Retransform-Classes" value="true"/>
|
虽然ant也没把依赖打进包里,但他创建了个lib目录并在manifest里写入了classpath的属性,所以可以跑起来。
然后启动命令是java -javaagent:'/home/zfn/NetBeansProjects/agent2/dist/agent2.jar' -jar awd.jar
好